package it.aekidna.cleverplatypus.mediator
{
	
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.setTimeout;
	
	import it.aekidna.cleverplatypus.utils.TaskDescriptor;
	
	import mx.core.EventPriority;
	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.utils.UIDUtil;

	public dynamic class CommandAsyncToken extends EventDispatcher implements IResponder
	{
		[ArrayElementType("mx.rpc.IResponder")]
		private var _responders : Array = [];
		private static var _tokens : Object = {};
		private var delegate : Object;
		private var id : String;
		public var simulateAsync : Boolean;
		
		public var taskDescriptor : TaskDescriptor;

		public function CommandAsyncToken( inDelegate : Object ) 
		{
			super();
			delegate = inDelegate;
			id = UIDUtil.createUID();
		}
		
		public function result( inData : Object ) : void
		{
			if( simulateAsync )
				setTimeout( doResult, 300, inData );
			else
				doResult( inData );
		}
		
		private function doResult( inData : Object ) : void
		{
			dispatchEvent( new ResultEvent( ResultEvent.RESULT, false, false, ResultEvent ( inData ).result ) );
			for each( var r : IResponder in _responders )
			{
				r.result( inData );
			}
			delete _tokens[id];
			delegate = null;
		}

		public function onResultEvent( inEvent : ResultEvent ) : void
		{
			IEventDispatcher( inEvent.target ).removeEventListener( FaultEvent.FAULT, onFaultEvent );
			IEventDispatcher( inEvent.target ).removeEventListener( ResultEvent.RESULT, onResultEvent );
			result( inEvent );
		}
		
		public function onFaultEvent( inEvent : FaultEvent ) : void
		{
			IEventDispatcher( inEvent.target ).removeEventListener( FaultEvent.FAULT, onFaultEvent );
			IEventDispatcher( inEvent.target ).removeEventListener( ResultEvent.RESULT, onResultEvent );
			fault( inEvent );
		}
		
		public function fault( inInfo : Object ) : void
		{
			if( simulateAsync )
				setTimeout( doFault, 300, inInfo );
			else
				doFault( inInfo );
		}
		
		private function doFault( inInfo : Object ) : void
		{
			dispatchEvent( new FaultEvent( FaultEvent.FAULT, false, true, FaultEvent( inInfo ).fault ) );
			for each( var r : IResponder in _responders )
			{
				r.fault( inInfo );
			}
			
			delete _tokens[id];
			delegate = null;
		}
		
		public function addResponder( inResponder : IResponder ) : void
		{
			_responders.push( inResponder );
			_tokens[ id ] = this;
		}
		
		override public function addEventListener(
			type:String, 
			listener:Function, 
			useCapture:Boolean=false, 
			priority:int=0, 
			useWeakReference:Boolean=false ) : void
		{
			super.addEventListener( type, listener, useCapture, priority, useWeakReference );
			_tokens[ id ] = this;
		}
		
		public function addListeners( 
			inResultFunction : Function, 
			inFaultFunction : Function = null, 
			inResultPriority : int = EventPriority.DEFAULT,
			inFaultPriority : int = EventPriority.DEFAULT ) : void
		{
			if( inResultFunction != null )
			{
				addEventListener( ResultEvent.RESULT, inResultFunction, false, inResultPriority );
			}
			if( inFaultFunction != null )
			{
				addEventListener( FaultEvent.FAULT, inFaultFunction, false, inFaultPriority );
			}
		}
	}
}